"""
TTS组件。
"""
import typing

from .base import BaseSession, BaseSessionType, BaseSessionParentType
from .framework import dispatch, session_received
from .utils import from_any, to_any, Any, Int32Value, StringValue


@session_received
class TextToSpeech(BaseSession):
    """
    文本到语音。
    """
    name = 'TextToSpeech'

    @classmethod
    async def create(cls: typing.Type[BaseSessionType], parent: BaseSessionParentType, *args: typing.Any,
                     **kwargs: typing.Dict) -> BaseSessionType:
        """
        创建tts对象时需要提供一个callback函数，当设备端的语音引擎创建完毕自动调用callback。
        只有在接受到callback后才表示实力初始化完毕，可以正常调用相关speak函数。
        """
        if len(args) < 1:
            raise TypeError('Missing 1 required positional argument: `onInitialize`.')
        on_initialize = parent.create_callback(args[0])
        return await super().create(parent,
                                    on_initialize,
                                    **kwargs)

    async def set_on_start_listener(self, func: typing.Optional[typing.Callable] = None):
        """
        设置当语音朗读开始的监听器。
        @func: 一个可调用的异步函数对象（需要实现utteranceId: str参数），如果是None则取消监听函数。
        调用示例：
        async def cb(utterance_id: str): ...
        await tts.set_on_start_listener(cb)
        """
        if not func:
            dispatch(self.send_action('setOnStartListener', to_any(None)))
            return

        async def inner(utterance_id: Any):
            """
            回调监听代理函数。
            @utteranceId: 调用speak函数时传入的utteranceId
            """
            if func:
                await func(from_any(utterance_id, StringValue))

        dispatch(self.send_action('setOnStartListener', self.create_callback(inner)))

    async def set_on_stop_listener(self, func: typing.Optional[typing.Callable] = None):
        """
        设置当语音朗读停止的监听器。
        @func: 一个可调用的异步函数对象（需要实现utteranceId: str参数），如果是None则取消监听函数。
        调用示例：
        async def cb(utterance_id: str): ...
        await tts.set_on_stop_listener(cb)
        """
        if not func:
            dispatch(self.send_action('setOnStopListener', to_any(None)))
            return

        async def inner(utterance_id: Any):
            """
            回调监听代理函数。
            @utteranceId: 调用speak函数时传入的utteranceId
            """
            if func:
                await func(from_any(utterance_id, StringValue))

        dispatch(self.send_action('setOnStopListener', self.create_callback(inner)))

    async def set_on_done_listener(self, func: typing.Optional[typing.Callable] = None):
        """
        设置当语音朗读完毕的监听器。
        @func: 一个可调用的异步函数对象（需要实现utteranceId: str参数），如果是None则取消监听函数。
        调用示例：
        async def cb(utterance_id: str): ...
        await tts.set_on_done_listener(cb)
        """
        if not func:
            dispatch(self.send_action('setOnDoneListener', to_any(None)))
            return

        async def inner(utterance_id: Any):
            """
            回调监听代理函数。
            @utteranceId: 调用speak函数时传入的utteranceId
            """
            if func:
                await func(from_any(utterance_id, StringValue))

        dispatch(self.send_action('setOnDoneListener', self.create_callback(inner)))

    async def set_on_error_listener(self, func: typing.Optional[typing.Callable] = None):
        """
        设置当语音朗读出错的监听器。
        @func: 一个可调用的异步函数对象（需要实现utteranceId: str和errorCode: int两个参数），如果是None则取消监听函数。
        调用示例：
        async def cb(utterance_id: str, error_code: int): ...
        await tts.set_on_error_listener(cb)
        """
        if not func:
            dispatch(self.send_action('setOnErrorListener', to_any(None)))
            return

        async def inner(utterance_id: Any, error_code: Any):
            """
            回调监听代理函数。
            @utteranceId: 调用speak函数时传入的utteranceId
            """
            if func:
                await func(from_any(utterance_id, StringValue), from_any(error_code, Int32Value))

        dispatch(self.send_action('setOnErrorListener', self.create_callback(inner)))

    async def speak(self, text: str, utterance_id: typing.Optional[str] = None):
        """
        朗读文字。
        @text: 要朗读的文字。
        @utteranceId: 朗读ID。
        """
        if utterance_id:
            dispatch(self.send_action('speak', to_any(text), to_any(utterance_id)))
            return
        dispatch(self.send_action('speak', to_any(text)))

    async def stop(self):
        """
        停止当前朗读。
        """
        dispatch(self.send_action('stop'))
